package com.trace.demo.controller;

import com.trace.demo.annotation.OperationLog;
import com.trace.demo.entity.TraceCode;
import com.trace.demo.entity.TraceQueryLog;
import com.trace.demo.entity.Product;
import com.trace.demo.repository.TraceCodeRepository;
import com.trace.demo.repository.TraceQueryLogRepository;
import com.trace.demo.repository.ProductRepository;
import com.trace.demo.response.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 溯源统计控制器
 */
@RestController
@RequestMapping("/api/trace-stats")
public class TraceStatsController {

    @Autowired
    private TraceCodeRepository traceCodeRepository;

    @Autowired
    private TraceQueryLogRepository traceQueryLogRepository;

    @Autowired
    private ProductRepository productRepository;

    /**
     * 获取基本统计数据
     * @return 统计数据
     */
    @GetMapping("/basic")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取基本统计数据")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getBasicStats() {
        Map<String, Object> stats = new HashMap<>();

        try {
            // 总溯源码数量
            long totalCodes = traceCodeRepository.count();
            stats.put("totalCodes", totalCodes);

            // 今日新增溯源码数量
            LocalDateTime startOfToday = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT);
            Date startDate = Date.from(startOfToday.atZone(ZoneId.systemDefault()).toInstant());
            long todayNewCodes = traceCodeRepository.countByCreatedAtAfter(startDate);
            stats.put("todayNewCodes", todayNewCodes);

            // 总查询次数
            long totalQueries = traceQueryLogRepository.count();
            stats.put("totalQueries", totalQueries);

            // 今日查询次数 - 尝试两种方式（优先使用scan_time）
            long todayQueries;
            try {
                todayQueries = traceQueryLogRepository.countByScanTimeAfter(startOfToday);
            } catch (Exception e) {
                // 如果scan_time方式失败，尝试query_time
                todayQueries = traceQueryLogRepository.countByQueryTimeAfter(startOfToday);
            }
            stats.put("todayQueries", todayQueries);

            return ResponseEntity.ok(new ApiResponse<>(true, "获取基本统计数据成功", stats));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取基本统计数据失败: " + e.getMessage(), stats));
        }
    }

    /**
     * 获取最近溯源查询记录
     * @param count 数量
     * @return 查询记录
     */
    @GetMapping("/recent-queries")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取最近溯源查询记录")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getRecentQueries(@RequestParam(defaultValue = "10") int count) {
        try {
            // 优先使用scan_time排序，如果失败则使用query_time
            PageRequest pageRequest = PageRequest.of(0, count, Sort.by(Sort.Direction.DESC, "scanTime"));
            List<TraceQueryLog> recentLogs;
            
            try {
                recentLogs = traceQueryLogRepository.findAllByOrderByScanTimeDesc(pageRequest).getContent();
            } catch (Exception e) {
                // 如果失败，尝试使用query_time
                PageRequest altPageRequest = PageRequest.of(0, count, Sort.by(Sort.Direction.DESC, "queryTime"));
                recentLogs = traceQueryLogRepository.findAllByOrderByQueryTimeDesc(altPageRequest).getContent();
            }
            
            // 转换为前端所需格式
            List<Map<String, Object>> result = recentLogs.stream().map(log -> {
                Map<String, Object> item = new HashMap<>();
                item.put("id", log.getId());
                
                // 从log对象获取trace_code - 优先使用code字段，如果为空则使用traceCode
                String traceCodeValue = (log.getCode() != null && !log.getCode().isEmpty()) ? 
                    log.getCode() : log.getTraceCode();
                item.put("traceCode", traceCodeValue);
                
                // 获取产品信息 - 先尝试从log对象直接获取产品名称
                if (log.getProductName() != null && !log.getProductName().isEmpty()) {
                    item.put("productName", log.getProductName());
                } else {
                    // 如果log对象没有产品名称，尝试通过关联查询获取
                    Optional<TraceCode> traceCodeOpt = traceCodeRepository.findByCodeOrTraceCode(traceCodeValue, traceCodeValue);
                    if (traceCodeOpt.isPresent()) {
                        TraceCode traceCode = traceCodeOpt.get();
                        Optional<Product> productOpt = productRepository.findById(traceCode.getProductId());
                        if (productOpt.isPresent()) {
                            item.put("productName", productOpt.get().getProductName());
                        } else {
                            item.put("productName", "未知产品");
                        }
                    } else {
                        item.put("productName", "未知产品");
                    }
                }
                
                // 获取查询位置 - 优先使用location字段，如果为空则使用queryLocation
                String locationValue = (log.getLocation() != null && !log.getLocation().isEmpty()) ? 
                    log.getLocation() : log.getQueryLocation();
                item.put("location", locationValue);
                
                // 获取设备类型 - 优先使用deviceType字段，如果为空则使用queryDevice
                String deviceValue = (log.getDeviceType() != null && !log.getDeviceType().isEmpty()) ? 
                    log.getDeviceType() : log.getQueryDevice();
                item.put("deviceType", deviceValue);
                
                // 获取查询时间 - 优先使用scanTime字段，如果为空则使用queryTime
                LocalDateTime timeValue = (log.getScanTime() != null) ? 
                    log.getScanTime() : log.getQueryTime();
                item.put("queryTime", timeValue);
                
                return item;
            }).collect(Collectors.toList());
            
            return ResponseEntity.ok(new ApiResponse<>(true, "获取最近查询记录成功", result));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取最近查询记录失败: " + e.getMessage(), new ArrayList<>()));
        }
    }

    /**
     * 获取查询趋势数据
     * @param days 天数
     * @return 趋势数据
     */
    @GetMapping("/query-trend")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取查询趋势数据")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getQueryTrend(@RequestParam(defaultValue = "7") int days) {
        try {
            Map<String, Object> result = new HashMap<>();
            List<String> dates = new ArrayList<>();
            List<Long> values = new ArrayList<>();
            
            LocalDate endDate = LocalDate.now();
            LocalDate startDate = endDate.minusDays(days - 1);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M月d日");
            
            for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
                LocalDateTime start = date.atStartOfDay();
                LocalDateTime end = date.atTime(23, 59, 59);
                
                // 查询当天的数据 - 尝试使用两种字段
                long count;
                try {
                    // 优先尝试使用scan_time字段
                    count = traceQueryLogRepository.countByScanTimeBetween(start, end);
                } catch (Exception e) {
                    // 如果失败，尝试使用query_time字段
                    count = traceQueryLogRepository.countByQueryTimeBetween(start, end);
                }
                
                // 添加到结果
                dates.add(date.format(formatter));
                values.add(count);
            }
            
            result.put("dates", dates);
            result.put("values", values);
            
            return ResponseEntity.ok(new ApiResponse<>(true, "获取查询趋势数据成功", result));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取查询趋势数据失败: " + e.getMessage(), new HashMap<>()));
        }
    }

    /**
     * 获取查询地区分布
     * @return 地区分布数据
     */
    @GetMapping("/region-distribution")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取查询地区分布")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getQueryRegionDistribution() {
        try {
            // 从数据库中获取地区分布数据 - 尝试两种方式
            List<Object[]> regionStats;
            try {
                // 优先尝试使用location字段
                regionStats = traceQueryLogRepository.findLocationStats();
                // 如果结果为空，尝试使用queryLocation字段
                if (regionStats == null || regionStats.isEmpty()) {
                    regionStats = traceQueryLogRepository.findQueryLocationStats();
                }
            } catch (Exception e) {
                // 如果第一种方式失败，尝试使用queryLocation字段
                regionStats = traceQueryLogRepository.findQueryLocationStats();
            }
            
            // 转换为前端所需格式
            List<Map<String, Object>> result = regionStats.stream().map(stat -> {
                Map<String, Object> item = new HashMap<>();
                item.put("name", stat[0] != null ? stat[0].toString() : "未知地区");
                item.put("value", stat[1]);
                return item;
            }).collect(Collectors.toList());
            
            return ResponseEntity.ok(new ApiResponse<>(true, "获取查询地区分布成功", result));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取查询地区分布失败: " + e.getMessage(), new ArrayList<>()));
        }
    }

    /**
     * 获取产品查询排行
     * @param count 数量
     * @return 产品排行数据
     */
    @GetMapping("/product-ranking")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取产品查询排行")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getProductQueryRanking(@RequestParam(defaultValue = "10") int count) {
        try {
            // 从数据库中获取产品查询排行
            List<Object[]> productStats = traceQueryLogRepository.findProductQueryStats(count);
            
            // 转换为前端所需格式
            List<Map<String, Object>> result = productStats.stream().map(stat -> {
                Map<String, Object> item = new HashMap<>();
                // 判断是否为null
                if (stat[0] != null) {
                    // 获取产品名称
                    Optional<Product> productOpt = productRepository.findById(Long.parseLong(stat[0].toString()));
                    if (productOpt.isPresent()) {
                        item.put("name", productOpt.get().getProductName());
                    } else {
                        item.put("name", "未知产品");
                    }
                } else {
                    item.put("name", "未知产品");
                }
                item.put("value", stat[1]); // 数量
                return item;
            }).collect(Collectors.toList());
            
            return ResponseEntity.ok(new ApiResponse<>(true, "获取产品查询排行成功", result));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取产品查询排行失败: " + e.getMessage(), new ArrayList<>()));
        }
    }

    /**
     * 获取设备类型分布
     * @return 设备类型分布数据
     */
    @GetMapping("/device-distribution")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取设备类型分布")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getDeviceTypeDistribution() {
        try {
            // 从数据库中获取设备类型分布 - 尝试两种方式
            List<Object[]> deviceStats;
            try {
                // 优先尝试使用deviceType字段
                deviceStats = traceQueryLogRepository.findDeviceStats();
                // 如果结果为空，尝试使用queryDevice字段
                if (deviceStats == null || deviceStats.isEmpty()) {
                    deviceStats = traceQueryLogRepository.findDeviceTypeStats();
                }
            } catch (Exception e) {
                // 如果第一种方式失败，尝试使用queryDevice字段
                deviceStats = traceQueryLogRepository.findDeviceTypeStats();
            }
            
            // 转换为前端所需格式
            List<Map<String, Object>> result = deviceStats.stream().map(stat -> {
                Map<String, Object> item = new HashMap<>();
                item.put("name", stat[0] != null ? stat[0].toString() : "未知设备");
                item.put("value", stat[1]);
                return item;
            }).collect(Collectors.toList());
            
            return ResponseEntity.ok(new ApiResponse<>(true, "获取设备类型分布成功", result));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取设备类型分布失败: " + e.getMessage(), new ArrayList<>()));
        }
    }
    
    /**
     * 获取浏览器分布
     * @return 浏览器分布数据
     */
    @GetMapping("/browser-distribution")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取浏览器分布")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getBrowserDistribution() {
        try {
            // 从数据库中获取浏览器分布
            List<Object[]> browserStats = traceQueryLogRepository.findBrowserStats();
            
            // 转换为前端所需格式
            List<Map<String, Object>> result = browserStats.stream().map(stat -> {
                Map<String, Object> item = new HashMap<>();
                item.put("name", stat[0] != null ? stat[0].toString() : "未知浏览器");
                item.put("value", stat[1]);
                return item;
            }).collect(Collectors.toList());
            
            return ResponseEntity.ok(new ApiResponse<>(true, "获取浏览器分布成功", result));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取浏览器分布失败: " + e.getMessage(), new ArrayList<>()));
        }
    }
    
    /**
     * 获取操作系统分布
     * @return 操作系统分布数据
     */
    @GetMapping("/os-distribution")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取操作系统分布")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getOsDistribution() {
        try {
            // 从数据库中获取操作系统分布
            List<Object[]> osStats = traceQueryLogRepository.findOsStats();
            
            // 转换为前端所需格式
            List<Map<String, Object>> result = osStats.stream().map(stat -> {
                Map<String, Object> item = new HashMap<>();
                item.put("name", stat[0] != null ? stat[0].toString() : "未知操作系统");
                item.put("value", stat[1]);
                return item;
            }).collect(Collectors.toList());
            
            return ResponseEntity.ok(new ApiResponse<>(true, "获取操作系统分布成功", result));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取操作系统分布失败: " + e.getMessage(), new ArrayList<>()));
        }
    }
    
    /**
     * 获取特定溯源码的统计数据
     * @param code 溯源码
     * @return 统计数据
     */
    @GetMapping("/{code}")
    @OperationLog(module = "溯源统计", action = "查询", description = "获取特定溯源码的统计数据")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getTraceStatsById(@PathVariable String code) {
        try {
            // 查询溯源码是否存在
            Optional<TraceCode> traceCodeOptional = traceCodeRepository.findByCodeOrTraceCode(code, code);
            if (!traceCodeOptional.isPresent()) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND)
                        .body(new ApiResponse<>(false, "溯源码不存在: " + code, null));
            }
            
            TraceCode traceCode = traceCodeOptional.get();
            
            // 创建结果映射
            Map<String, Object> stats = new HashMap<>();
            
            // 基本信息
            stats.put("traceCode", traceCode.getCode());
            stats.put("id", traceCode.getId());
            stats.put("batchId", traceCode.getBatchId());
            stats.put("productId", traceCode.getProductId());
            stats.put("status", traceCode.getStatus());
            stats.put("createdAt", traceCode.getCreatedAt());
            
            // 获取产品信息
            Optional<Product> productOptional = productRepository.findById(traceCode.getProductId());
            if (productOptional.isPresent()) {
                Product product = productOptional.get();
                stats.put("productName", product.getProductName());
                stats.put("productCode", product.getProductCode());
                stats.put("category", product.getCategory());
            }
            
            // 查询统计
            long totalQueries = traceQueryLogRepository.countByCodeOrTraceCode(code, code);
            stats.put("totalQueries", totalQueries);
            
            // 今日查询次数
            LocalDateTime startOfToday = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT);
            long todayQueries = 0;
            try {
                todayQueries = traceQueryLogRepository.countByCodeAndScanTimeAfter(code, startOfToday);
            } catch (Exception e) {
                // 如果scan_time方式失败，尝试query_time
                todayQueries = traceQueryLogRepository.countByCodeAndQueryTimeAfter(code, startOfToday);
            }
            stats.put("todayQueries", todayQueries);
            
            // 最近查询记录
            List<TraceQueryLog> recentQueries;
            try {
                PageRequest pageRequest = PageRequest.of(0, 5, Sort.by(Sort.Direction.DESC, "scanTime"));
                recentQueries = traceQueryLogRepository.findByCodeOrderByScanTimeDesc(code, pageRequest);
            } catch (Exception e) {
                // 如果scan_time方式失败，尝试query_time
                PageRequest pageRequest = PageRequest.of(0, 5, Sort.by(Sort.Direction.DESC, "queryTime"));
                recentQueries = traceQueryLogRepository.findByCodeOrderByQueryTimeDesc(code, pageRequest);
            }
            
            // 转换最近查询为前端所需格式
            List<Map<String, Object>> formattedQueries = recentQueries.stream().map(query -> {
                Map<String, Object> item = new HashMap<>();
                item.put("id", query.getId());
                item.put("time", query.getScanTime() != null ? query.getScanTime() : query.getQueryTime());
                item.put("location", query.getLocation() != null ? query.getLocation() : query.getQueryLocation());
                item.put("deviceType", query.getDeviceType() != null ? query.getDeviceType() : query.getQueryDevice());
                return item;
            }).collect(Collectors.toList());
            
            stats.put("recentQueries", formattedQueries);
            
            return ResponseEntity.ok(new ApiResponse<>(true, "获取溯源码统计数据成功", stats));
        } catch (Exception e) {
            return ResponseEntity.ok(new ApiResponse<>(false, "获取溯源码统计数据失败: " + e.getMessage(), null));
        }
    }
} 